bitkeeper revision 1.882 (4092efb3iUwNww3oOZDLfH3rovuyhg)
authoriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Sat, 1 May 2004 00:30:43 +0000 (00:30 +0000)
committeriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Sat, 1 May 2004 00:30:43 +0000 (00:30 +0000)
suspend uses new batched getpageinfo interface

tools/examples/xc_dom_control.py
tools/xc/lib/xc_linux_save.c
tools/xc/lib/xc_private.c
tools/xc/lib/xc_private.h
xen/common/dom0_ops.c
xen/include/hypervisor-ifs/dom0_ops.h

index 080af6f366bb2fb46c89bb9d07c326eff9296c90..4f0bd5de528fbc6daf6e6282629f0e3b8a8996c5 100755 (executable)
@@ -137,7 +137,10 @@ elif cmd == 'suspend':
         os.kill(pid, signal.SIGTERM)
 
     xc.domain_stop( dom=dom )
-    time.sleep(0.1);
+    
+    while not xc.domain_getinfo( first_dom=dom, max_doms=1 )[0]['stopped']:
+       time.sleep(0.1);
+
     rc = xc.linux_save( dom=dom, state_file=file, progress=1)
     if rc == 0 : xc.domain_destroy( dom=dom, force=1 )
 
index 0a367234de943ec273a609983d14641b7afdcf82..fb6fbd6f575d3c4497b3574c4167292740903459 100644 (file)
@@ -10,6 +10,8 @@
 #include <asm-xen/suspend.h>
 #include <zlib.h>
 
+#define BATCH_SIZE 512   /* 1024 pages (4MB) at a time */
+
 /* This may allow us to create a 'quiet' command-line option, if necessary. */
 #define verbose_printf(_f, _a...) \
     do {                          \
     _res;                                   \
 })
 
-static int check_pfn_ownership(int xc_handle, 
-                               unsigned long mfn, 
-                               u64 dom)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETPAGEFRAMEINFO;
-    op.u.getpageframeinfo.pfn    = mfn;
-    op.u.getpageframeinfo.domain = (domid_t)dom;
-    return (do_dom0_op(xc_handle, &op) >= 0);
-}
 
-#define GETPFN_ERR (~0U)
-static unsigned int get_pfn_type(int xc_handle, 
-                                 unsigned long mfn, 
-                                 u64 dom)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETPAGEFRAMEINFO;
-    op.u.getpageframeinfo.pfn    = mfn;
-    op.u.getpageframeinfo.domain = (domid_t)dom;
-    if ( do_dom0_op(xc_handle, &op) < 0 )
-    {
-        PERROR("Unexpected failure when getting page frame info!");
-        return GETPFN_ERR;
-    }
-    return op.u.getpageframeinfo.type;
-}
 
 static int checked_write(gzFile fd, void *buf, size_t count)
 {
@@ -281,28 +257,59 @@ int xc_linux_save(int xc_handle,
 
 
     /*
-     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
-     * loop we have each MFN mapped at most once. Note that there may be MFNs
-     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
+     * Quick sanity check.
      */
 
     for ( i = 0; i < srec.nr_pfns; i++ )
     {
         mfn = live_pfn_to_mfn_table[i];
 
-#if 1  /* XXX use the master mfn_to_pfn table???? */
-
-
        if( live_mfn_to_pfn_table[mfn] != i )
            printf("i=%d mfn=%d live_mfn_to_pfn_table=%d\n",
                   i,mfn,live_mfn_to_pfn_table[mfn]);
+    }
 
-        /* Query page type by MFN, but store it by PFN. */
-        if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) == 
-             GETPFN_ERR )
-            goto out;
-#endif
 
+/* test new pfn_type stuff */
+    {
+       int n, i, j;
+
+       if ( mlock( pfn_type, srec.nr_pfns * sizeof(unsigned long) ) )
+       {
+           ERROR("Unable to mlock");
+           goto out;
+       }
+       for ( n = 0; n < srec.nr_pfns; )
+       {
+
+           for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
+           {           
+               pfn_type[i] = live_pfn_to_mfn_table[i];
+           }
+
+           if ( get_pfn_type_batch(xc_handle, domid, j, &pfn_type[n]) )
+           {
+               ERROR("get_pfn_type_batch failed");
+               goto out;
+           }
+
+           for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
+           {
+               
+               pfn_type[i] >>= 29;
+
+               if(pfn_type[i] == 7)
+               {
+                   ERROR("bogus page");
+                   goto out;
+               }
+
+/*             if(pfn_type[i])
+                   printf("i=%d type=%d\n",i,pfn_type[i]);    */
+           }
+
+           n+=j;
+       }
     }
 
 
@@ -354,13 +361,6 @@ int xc_linux_save(int xc_handle,
         goto out;
     }
 
-    /* Belts and braces safety check on the shared info record */
-    if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) )
-    {
-        ERROR("Invalid shared_info_frame");
-        goto out;
-    }
-
     if ( !checked_write(gfd, "LinuxGuestRecord",    16) ||
          !checked_write(gfd, name,                  sizeof(name)) ||
          !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
@@ -376,8 +376,6 @@ int xc_linux_save(int xc_handle,
 
     verbose_printf("Saving memory pages:   0%%");
 
-#define BATCH_SIZE 1024   /* 1024 pages (4MB) at a time */
-
     if ( (mapper_handle2 = mfn_mapper_init(xc_handle, domid,
                                           BATCH_SIZE*4096, PROT_READ )) 
         == NULL )
index 0c9092b607f295360c5351e86355fe363bdb7bc0..d137176ca80e32a158a304612aa82c93011a326b 100644 (file)
@@ -168,29 +168,7 @@ void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset,
 
 /*******************/
 
-typedef struct dom0_op_compact_getpageframeinfo {
-    unsigned long cmd;
-    unsigned long interface_version; /* DOM0_INTERFACE_VERSION */
-    dom0_getpageframeinfo_t getpageframeinfo;
-}  dom0_op_compact_getpageframeinfo_t;
-
-
-typedef struct mfn_typer {
-    domid_t dom;
-    int max;
-    int nr_multicall_ents;
-    multicall_entry_t *multicall_list;
-    dom0_op_compact_getpageframeinfo_t *gpf_list;
-} mfn_typer_t;
-
-
-mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num );
-
-void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn );
-
-int mfn_typer_flush_queue(mfn_typer_t *t);
-
-unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx);
+#if 0
 
 mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
 {
@@ -199,8 +177,8 @@ mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
     dom0_op_compact_getpageframeinfo_t *d;
 
     t = calloc(1, sizeof(mfn_typer_t) );
-    m = calloc(1, sizeof(multicall_entry_t)*num );
-    d = calloc(1, sizeof(dom0_op_compact_getpageframeinfo_t)*num );
+    m = calloc(num, sizeof(multicall_entry_t));
+    d = calloc(num, sizeof(dom0_op_compact_getpageframeinfo_t));
 
     if (!t || !m || !d)
     {
@@ -210,6 +188,16 @@ mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
        return NULL;
     }
 
+printf("sizeof(m)=%d sizeof(d)=%d m=%p d=%p\n",sizeof(multicall_entry_t), sizeof(dom0_op_compact_getpageframeinfo_t),m,d);
+
+    if ( (mlock(m, sizeof(multicall_entry_t)*num ) != 0) || 
+        (mlock(d, sizeof(dom0_op_compact_getpageframeinfo_t)*num ) != 0) )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        return NULL;
+    }
+    
+    t->xc_handle = xc_handle;
     t->max = num;
     t->nr_multicall_ents=0;
     t->multicall_list=m;
@@ -229,7 +217,7 @@ void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn )
     d->interface_version = DOM0_INTERFACE_VERSION;
     d->getpageframeinfo.pfn = mfn;
     d->getpageframeinfo.domain = t->dom;
-    d->getpageframeinfo.type = ~0UL;
+    d->getpageframeinfo.type = 1000; //~0UL;
       
     m->op = __HYPERVISOR_dom0_op;
     m->args[0] = (unsigned long)d;
@@ -240,7 +228,7 @@ void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn )
 int mfn_typer_flush_queue(mfn_typer_t *t)
 {
     if (t->nr_multicall_ents == 0) return 0;
-    (void)HYPERVISOR_multicall(t->multicall_list, t->nr_multicall_ents);
+    do_multicall_op(t->xc_handle, t->multicall_list, t->nr_multicall_ents);
     t->nr_multicall_ents = 0;
 }
 
@@ -249,6 +237,38 @@ unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx)
     return t->gpf_list[idx].getpageframeinfo.type;
 }
 
+#endif
+
+/* NB: arr must be mlock'ed */
+
+int get_pfn_type_batch(int xc_handle, 
+                      u64 dom, int num, unsigned long *arr)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETPAGEFRAMEINFO2;
+    op.u.getpageframeinfo2.domain = (domid_t)dom;
+    op.u.getpageframeinfo2.num    = num;
+    op.u.getpageframeinfo2.array  = arr;
+    return do_dom0_op(xc_handle, &op);
+}
+
+#define GETPFN_ERR (~0U)
+unsigned int get_pfn_type(int xc_handle, 
+                         unsigned long mfn, 
+                         u64 dom)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETPAGEFRAMEINFO;
+    op.u.getpageframeinfo.pfn    = mfn;
+    op.u.getpageframeinfo.domain = (domid_t)dom;
+    if ( do_dom0_op(xc_handle, &op) < 0 )
+    {
+        PERROR("Unexpected failure when getting page frame info!");
+        return GETPFN_ERR;
+    }
+    return op.u.getpageframeinfo.type;
+}
+
 
 
 /*******************/
index 198c703eaf4c58154ab8afe9cdcefb22bbb06efe..eaa301772d8722a316d5205181c0216038eb99e2 100644 (file)
@@ -110,6 +110,27 @@ static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
  out1: return ret;
 }
 
+static inline int do_multicall_op(int xc_handle, 
+                                 void *call_list, int nr_calls) 
+{
+    int ret = -1;
+    privcmd_hypercall_t hypercall;
+
+    hypercall.op     = __HYPERVISOR_multicall;
+    hypercall.arg[0] = (unsigned long)call_list;
+    hypercall.arg[1] = (unsigned long)nr_calls;
+
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+    {
+        if ( errno == EACCES )
+            fprintf(stderr, "Dom0 operation failed -- need to"
+                    " rebuild the user-space tool set?\n");
+        goto out1;
+    }
+
+ out1: return ret;
+}
+
 static inline int do_network_op(int xc_handle, network_op_t *op)
 {
     int ret = -1;
@@ -222,5 +243,31 @@ int mfn_mapper_flush_queue(mfn_mapper_t *t);
 void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 
                              unsigned long mfn, int size );
 
+/*********************/
+
+
+#if 0
+typedef struct mfn_typer {
+    domid_t dom;
+    int xc_handle;
+    int max;
+    dom0_op_t op;
+} mfn_typer_t;
+
+
+mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num );
+
+void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn );
+
+int mfn_typer_flush_queue(mfn_typer_t *t);
+#endif
+
+int get_pfn_type_batch(int xc_handle, 
+                      u64 dom, int num, unsigned long *arr);
+
+unsigned int get_pfn_type(int xc_handle, 
+                         unsigned long mfn, 
+                         u64 dom);
+    
 
 #endif /* __XC_PRIVATE_H__ */
index c6ca8149c6bfeee3f0881b30ff56b373313f1920..ef0ab2e81bbb913594deaef811e5a6be05b83f57 100644 (file)
@@ -564,6 +564,84 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     }
     break;
 
+    case DOM0_GETPAGEFRAMEINFO2:
+    {
+#define GPF2_BATCH 128
+       int n,j;
+        int num = op->u.getpageframeinfo2.num;
+        domid_t dom = op->u.getpageframeinfo2.domain;
+       unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array;
+        struct task_struct *p;
+       unsigned long l_arr[GPF2_BATCH];
+        ret = -ESRCH;
+
+       if ( unlikely((p = find_domain_by_id(dom)) == NULL) )
+           break;
+
+       if ( unlikely(num>1024) )
+       {
+           ret = -E2BIG;
+           break;
+       }
+       
+       ret = 0;    
+       for(n=0;n<num;)
+       {
+           int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
+
+           if( copy_from_user( l_arr, &s_ptr[n], k*sizeof(unsigned long) ) )
+           {
+               ret = -EINVAL;
+               break;
+           }
+           
+           for(j=0;j<k;j++)
+           {               
+               struct pfn_info *page;
+               unsigned long mfn = l_arr[j];
+
+               if ( unlikely(mfn >= max_page) )
+                   goto e2_err;
+
+               page = &frame_table[mfn];
+               
+               if ( likely(get_page(page, p)) )
+               {
+                   unsigned long type = 0;
+                   switch( page->type_and_flags & PGT_type_mask )
+                   {
+                   case PGT_l1_page_table:
+                   case PGT_l2_page_table:
+                   case PGT_l3_page_table:
+                   case PGT_l4_page_table:
+                       type = page->type_and_flags & PGT_type_mask;
+
+                   }
+                   l_arr[j] |= type;
+                   put_page(page);
+               }
+               else
+               {
+               e2_err:
+                   l_arr[j] |= PGT_type_mask; /* error */
+               }
+
+           }
+
+           if( copy_to_user( &s_ptr[n], l_arr, k*sizeof(unsigned long) ) )
+           {
+               ret = -EINVAL;
+               break;
+           }
+
+           n+=j;           
+       }
+
+       put_task_struct(p);
+
+    }
+    break;
+
     default:
         ret = -ENOSYS;
 
index e943338a0d38b01fc1cb667e7a053c1e2f2afa52..3bc18476afe756e11d310e4dbb4624a6a833dfa8 100644 (file)
@@ -266,6 +266,16 @@ typedef struct dom0_setdomainmaxmem_st
     unsigned int max_memkb;
 } dom0_setdomainmaxmem_t;
 
+#define DOM0_GETPAGEFRAMEINFO2 29   /* batched interface */
+typedef struct dom0_getpageframeinfo2_st
+{
+    /* IN variables. */
+    domid_t domain;        /* To which domain do frames belong?    */    
+    int num;
+    /* IN/OUT variables. */
+    unsigned long *array;
+} dom0_getpageframeinfo2_t;
+
 
 typedef struct dom0_op_st
 {
@@ -297,6 +307,7 @@ typedef struct dom0_op_st
        dom0_setdomainname_t    setdomainname;
        dom0_setdomaininitialmem_t setdomaininitialmem;
        dom0_setdomainmaxmem_t  setdomainmaxmem;
+       dom0_getpageframeinfo2_t getpageframeinfo2;
     } u;
 } dom0_op_t;